package com.example.web.service.impl;

import com.example.web.entity.SequenceConfig;
import com.example.web.entity.SequenceRegistry;
import com.example.web.mapper.SequenceConfigMapper;
import com.example.web.mapper.SequenceRegistryMapper;
import com.example.web.service.SequenceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class SequenceServiceImpl implements SequenceService {
    
    @Autowired
    private SequenceConfigMapper configMapper;
    
    @Autowired
    private SequenceRegistryMapper registryMapper;
    
    @Override
    public Map<String, Object> getConfigList(Integer page, Integer size, String name, String code) {
        Map<String, Object> result = new HashMap<>();
        
        int offset = (page - 1) * size;
        List<SequenceConfig> list = configMapper.findConfigs(name, code, offset, size);
        Long total = configMapper.countConfigs(name, code);
        
        result.put("list", list);
        result.put("total", total);
        result.put("page", page);
        result.put("size", size);
        
        return result;
    }
    
    @Override
    public SequenceConfig findById(String id) {
        return configMapper.findById(id);
    }
    
    @Override
    public SequenceConfig findByCode(String code) {
        return configMapper.findByCode(code);
    }
    
    @Override
    @Transactional
    public SequenceConfig createConfig(SequenceConfig config) {
        // 生成ID
        config.setId(UUID.randomUUID().toString().replace("-", ""));
        
        // 检查编码是否已存在
        SequenceConfig existing = configMapper.findByCode(config.getCode());
        if (existing != null) {
            throw new RuntimeException("配置编码已存在");
        }
        
        configMapper.insert(config);
        return config;
    }
    
    @Override
    @Transactional
    public SequenceConfig updateConfig(SequenceConfig config) {
        // 检查配置是否存在
        SequenceConfig existing = configMapper.findById(config.getId());
        if (existing == null) {
            throw new RuntimeException("配置不存在");
        }
        
        // 如果修改了编码，检查新编码是否已被使用
        if (!existing.getCode().equals(config.getCode())) {
            SequenceConfig codeExisting = configMapper.findByCode(config.getCode());
            if (codeExisting != null) {
                throw new RuntimeException("配置编码已存在");
            }
        }
        
        configMapper.update(config);
        return configMapper.findById(config.getId());
    }
    
    @Override
    @Transactional
    public boolean deleteConfig(String id) {
        int rows = configMapper.deleteById(id);
        return rows > 0;
    }
    
    @Override
    @Transactional
    public String generateSequence(String code) {
        // 1. 查询配置
        SequenceConfig config = configMapper.findByCode(code);
        if (config == null) {
            throw new RuntimeException("配置不存在或无效");
        }
        
        // 2. 生成前缀
        String prefix = generatePrefix(config);
        
        // 3. 查询或创建注册记录
        SequenceRegistry registry = registryMapper.findByNameAndPrefix(config.getName(), prefix);
        if (registry == null) {
            // 首次生成，创建注册记录
            registry = new SequenceRegistry();
            registry.setId(UUID.randomUUID().toString().replace("-", ""));
            registry.setName(config.getName());
            registry.setPrefix(prefix);
            registry.setNextValue(config.getMinValue() != null ? config.getMinValue() : 0L);
            registry.setMinValue(config.getMinValue() != null ? config.getMinValue() : 0L);
            registry.setInitValue(config.getMinValue() != null ? config.getMinValue() : 0L);
            registry.setMaxValue(config.getMaxValue() != null ? config.getMaxValue() : Long.MAX_VALUE);
            registry.setCycle(config.getCycle());
            registry.setStep(config.getStep().longValue());
            registryMapper.insert(registry);
        }
        
        // 4. 计算下一个值
        Long currentValue = registry.getNextValue();
        Long nextValue = currentValue + registry.getStep();
        
        // 5. 边界判断
        boolean valueRangeEnabled = "true".equals(config.getValueRange());
        if (valueRangeEnabled && nextValue > registry.getMaxValue()) {
            // 超出最大值
            if ("1".equals(registry.getCycle())) {
                // 允许回滚，重置为最小值
                nextValue = registry.getMinValue();
            } else {
                // 不允许回滚，抛出异常
                throw new RuntimeException("超出取值范围");
            }
        }
        
        // 6. 原子更新下一个值
        int updated = registryMapper.updateNextValue(registry.getId(), currentValue, nextValue);
        if (updated == 0) {
            // 并发冲突，重试
            throw new RuntimeException("生成序列号失败，请重试");
        }
        
        // 7. 格式化当前值
        String coreSequence = formatCoreSequence(currentValue, config);
        
        // 8. 拼接最终序列号
        String suffix = generateSuffix(config);
        return prefix + coreSequence + suffix;
    }
    
    /**
     * 生成前缀
     */
    private String generatePrefix(SequenceConfig config) {
        if ("TIME".equals(config.getPrefixType())) {
            // 时间格式前缀
            String timeFormat = config.getTimePrefix();
            if (timeFormat == null || timeFormat.isEmpty()) {
                timeFormat = "yyyyMMdd";
            }
            SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
            return sdf.format(new Date());
        } else {
            // 文本前缀
            return config.getPrefix() != null ? config.getPrefix() : "";
        }
    }
    
    /**
     * 生成后缀
     */
    private String generateSuffix(SequenceConfig config) {
        if ("true".equals(config.getSuffixConf())) {
            return config.getSuffix() != null ? config.getSuffix() : "";
        }
        return "";
    }
    
    /**
     * 格式化核心序列号（补0）
     */
    private String formatCoreSequence(Long value, SequenceConfig config) {
        String valueStr = String.valueOf(value);
        
        // 检查是否需要补全长度
        if ("true".equals(config.getCompletion()) && config.getLength() != null) {
            int length = config.getLength();
            while (valueStr.length() < length) {
                valueStr = "0" + valueStr;
            }
        }
        
        return valueStr;
    }
}
